/**
 * Copyright 2021 Huawei Technologies Co., Ltd
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "inc/utils.h"

#include <fstream>
#include <algorithm>
#include <iostream>
#include <sstream>
using mindspore::MSTensor;
using mindspore::DataType;


std::vector<std::string> GetAlldir(const std::string& dir_name, const std::string_view& data_name) {
    std::vector<std::string> res;
    if (data_name == "TUM") {
        std::string txt_name = dir_name + "/associate.txt";
        std::ifstream infile;
        infile.open(txt_name.data());
        std::string s;
        while (getline(infile, s)) {
            std::stringstream input(s);
            std::string result;
            input >> result;
            res.emplace_back(dir_name + "/" + result);
        }
        return res;
    }
    struct dirent *filename;
    DIR *dir = OpenDir(dir_name);
    if (dir == nullptr) {
    return {};
    }

    if (data_name == "Kitti") {
        while ((filename = readdir(dir)) != nullptr) {
            std::string d_name = std::string(filename->d_name);
            // get rid of "." and ".."
            if (d_name == "." || d_name == ".." || filename->d_type != DT_DIR)
            continue;
            res.emplace_back(d_name + "/image");
            std::cout << "image_file name is " << d_name << std::endl;
        }
    } else if (data_name == "Sintel") {
        while ((filename = readdir(dir)) != nullptr) {
            std::string d_name = std::string(filename->d_name);
            // get rid of "." and ".."
            if (d_name == "." || d_name == ".." || filename->d_type != DT_DIR)
            continue;
            res.emplace_back(d_name);
        }
    }


    return res;
}

int WriteResult(const std::string& imageFile, const std::vector<MSTensor> &outputs,
                const std::string & dataset_name, const std::string& seq) {
    std::string homePath;
    if (dataset_name == "Kitti") {
        int pos = seq.find('/');
        std::string seq1(seq, 0, pos);
        homePath = "./result_Files/"+ dataset_name + "/" + seq1;
        std::cout << "1" << std::endl;
    } else {
        homePath = "./result_Files/"+ dataset_name + "/" + seq;
    }
    std::string path1 = "mkdir " + homePath;
    system(path1.c_str());
    std::cout << "homePath is " << homePath << std::endl;
    for (size_t i = 0; i < outputs.size(); ++i) {
        size_t outputSize;
        std::shared_ptr<const void> netOutput = outputs[i].Data();
        outputSize = outputs[i].DataSize();
        int pos = imageFile.rfind('/');
        std::string fileName(imageFile, pos + 1);
        fileName.replace(fileName.rfind('.'), fileName.size() - fileName.rfind('.'), '_' + std::to_string(i) + ".bin");
        std::string outFileName = homePath + "/" + fileName;
        std::cout << "output file is " << outFileName << std::endl;
        FILE *outputFile = fopen(outFileName.c_str(), "wb");
        fwrite(netOutput.get(), outputSize, sizeof(char), outputFile);
        fclose(outputFile);
        outputFile = nullptr;
    }
    return 0;
}


std::vector<std::string> GetAllFiles(std::string_view dirName) {
    struct dirent *filename;
    DIR *dir = OpenDir(dirName);
     std::cout << dirName << std::endl;
    if (dir == nullptr) {
        return {};
    }
    std::vector<std::string> res;
    while ((filename = readdir(dir)) != nullptr) {
        std::string dName = std::string(filename->d_name);
        if (dName == "." || dName == ".." || filename->d_type != DT_REG) {
            continue;
        }
        res.emplace_back(std::string(dirName) + "/" + filename->d_name);
    }
    std::sort(res.begin(), res.end());
    for (auto &f : res) {
        std::cout << "image file: " << f << std::endl;
    }
    return res;
}


mindspore::MSTensor ReadFileToTensor(const std::string &file) {
  if (file.empty()) {
    std::cout << "Pointer file is nullptr" << std::endl;
    return mindspore::MSTensor();
  }

  std::ifstream ifs(file);
  if (!ifs.good()) {
    std::cout << "File: " << file << " is not exist" << std::endl;
    return mindspore::MSTensor();
  }

  if (!ifs.is_open()) {
    std::cout << "File: " << file << "open failed" << std::endl;
    return mindspore::MSTensor();
  }

  ifs.seekg(0, std::ios::end);
  size_t size = ifs.tellg();
  mindspore::MSTensor buffer(file, mindspore::DataType::kNumberTypeUInt8, {static_cast<int64_t>(size)}, nullptr, size);

  ifs.seekg(0, std::ios::beg);
  ifs.read(reinterpret_cast<char *>(buffer.MutableData()), size);
  ifs.close();

  return buffer;
}

DIR *OpenDir(std::string_view dirName) {
    if (dirName.empty()) {
        std::cout << " dirName is null ! " << std::endl;
        return nullptr;
    }
    std::string realPath = RealPath(dirName);
    struct stat s;
    lstat(realPath.c_str(), &s);
    if (!S_ISDIR(s.st_mode)) {
        std::cout << "dirName is not a valid directory !" << std::endl;
        return nullptr;
    }
    DIR *dir = opendir(realPath.c_str());
    if (dir == nullptr) {
        std::cout << "Can not open dir " << dirName << std::endl;
        return nullptr;
    }
    std::cout << "Successfully opened the dir " << dirName << std::endl;
    return dir;
}


std::string RealPath(std::string_view path) {
    char realPathMem[PATH_MAX] = {0};
    char *realPathRet = nullptr;
    realPathRet = realpath(path.data(), realPathMem);
    if (realPathRet == nullptr) {
        std::cout << "File: " << path << " is not exist.";
        return "";
    }

    std::string realPath(realPathMem);
    std::cout << path << " realpath is: " << realPath << std::endl;
    return realPath;
}
